package com.zaoqi.aop;

import com.alibaba.fastjson.JSONObject;
import com.zaoqi.mapper.OperateLogMapper;
import com.zaoqi.pojo.OperateLog;
import com.zaoqi.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OperateLogMapper operateLogMapper;

    @Around("@annotation(com.zaoqi.anno.Log) || @within(com.zaoqi.anno.Log)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前方法名
        String methodName = joinPoint.getSignature().getName();
        log.info(methodName);
        // 如果是注册登录方法，跳过JWT解析
        if (methodName.equals("login")||methodName.equals("register")||methodName.equals("getPermissionsByUserId")) {
            return joinPoint.proceed();
        }
            String jwt = request.getHeader("Authorization").substring(7);
            log.info("jwt读取为：{}", jwt);
            Claims claims = JwtUtils.parseJWT(jwt);
            log.info("claims读取为：{}", claims);
            String operateUser = (String) claims.get("username");
            LocalDateTime operateTime = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String formattedTime = operateTime.format(formatter);
            String className = joinPoint.getTarget().getClass().getName();
            Object[] args = joinPoint.getArgs();
            String methodParams = Arrays.toString(args);
            long begin = System.currentTimeMillis();
            Object result;
            String returnValue = null;
            long costTime;
            try {
                result = joinPoint.proceed();
                returnValue = JSONObject.toJSONString(result);
            } catch (Throwable throwable) {
                log.error("Method {} in {} failed", methodName, className, throwable);
                throw throwable;
            } finally {
                long end = System.currentTimeMillis();
                costTime = end - begin;
                OperateLog operateLog = new OperateLog(null, operateUser, formattedTime, className, methodName, methodParams, returnValue, costTime);
                operateLogMapper.insert(operateLog);
                log.info("AOP记录操作日志：{}", operateLog);
            }
            return result;
    }
}

